package fs2

import (
	"github.com/sirupsen/logrus"
	"mydocker/common"
	"os"
	"path"
	"strconv"
)

// UnifiedMountPoint Cgroup V2 默认的统一的挂载点路径
const UnifiedMountPoint = "/sys/fs/cgroup"

// getCgroupPath 获取 cgroup 在文件系统中的绝对路径
/*
实际就是将根目录和 cgroup 名称拼接成一个路径。
如果指定了自动创建，就先检查一下是否存在，如果对应的目录不存在，则说明 cgroup 不存在，就创建一个。
因为 Cgroup V2 采用单一统一的层次结构设计，所有控制器和资源管理都在这一个层次结构中进行。
所以只有一个层次结构，位于 sys/fs/cgroup，所以不需要额外的 subsystem 参数。
*/
func getCgroupPath(cgroupPath string, autoCreate bool) (string, error) {
	cgroupRootPath := UnifiedMountPoint
	// 绝对路径
	absPath := path.Join(cgroupRootPath, cgroupPath)
	if !autoCreate { // 不需要自动创建时就直接返回
		return absPath, nil
	}
	// 判断文件是否已经存在
	_, err := os.Stat(absPath)
	if err != nil && os.IsNotExist(err) {
		if err = os.MkdirAll(absPath, common.Perm0755); err != nil {
			return "", err
		}
	}
	return absPath, nil
}

// applyCgroup 因为在 v2 中只有一个层次结构，所以不需要因为 subsystem（cpu、cpuset、memory） 的不同来分不同的情况，一个函数就可以搞定了
func applyCgroup(pid int, cgroupPath string) error {
	subCgroupPath, err := getCgroupPath(cgroupPath, true)
	if err != nil {
		logrus.Errorf("get cgroup path failed, err:%v", err)
		return err
	}
	if err = os.WriteFile(path.Join(subCgroupPath, "cgroup.procs"), []byte(strconv.Itoa(pid)), common.Perm0644); err != nil {
		logrus.Errorf("set cgroup proc fail %v", err)
		return err
	}
	return nil
}
